package com.xuzhiguang.lightnat.server.core.server.proxy.handler;

import com.xuzhiguang.lightnat.common.manager.ProxyChannelManager;
import com.xuzhiguang.lightnat.common.message.NatMessage;
import com.xuzhiguang.lightnat.common.serializer.SerializerTypeEnum;
import com.xuzhiguang.lightnat.server.core.client.NatClientService;
import com.xuzhiguang.lightnat.server.core.client.NatProxy;
import com.xuzhiguang.lightnat.server.core.server.proxy.refuse.RefuseStrategyFactory;
import com.xuzhiguang.lightnat.server.core.server.proxy.util.ProxyUtil;
import com.xuzhiguang.lightnat.server.core.server.transfer.TransferChannelManager;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;

@Slf4j
@ChannelHandler.Sharable
public class TransferHandler extends SimpleChannelInboundHandler<ByteBuf> {

    private final NatClientService natClientService;

    public TransferHandler(NatClientService natClientService) {
        this.natClientService = natClientService;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {

        log.debug("proxy transfer. channel:{}", ctx.channel());

        NatProxy natProxy = ProxyUtil.getNatProxy((InetSocketAddress) ctx.channel().localAddress(), natClientService);
        if (ProxyUtil.checkNatProxy(natProxy, ctx.channel())) {

            Long transferId = ProxyChannelManager.getTransferId(ctx.channel());
            if (transferId == null) {
                log.warn("transferId is null. channel id:{}", ctx.channel());
                RefuseStrategyFactory.getStrategy(natProxy.getProxyType()).refuse(ctx.channel(), "transferId is null");
                return;
            }

            Channel transferChannel = TransferChannelManager.getChannel(transferId);
            if (transferChannel == null) {
                log.warn("transferChannel is null. transferId:{}", transferId);
                RefuseStrategyFactory.getStrategy(natProxy.getProxyType()).refuse(ctx.channel(), "transferChannel is null");
                return;
            }

            // transfer 将数据转发到 client
            byte[] bodyData = new byte[msg.readableBytes()];
            msg.readBytes(bodyData);
            NatMessage natMessage = new NatMessage(bodyData, SerializerTypeEnum.BYTE.getType());
            transferChannel.writeAndFlush(natMessage);
        }
    }
}
